---
sidebar_position: 2
---

# Отличительные особенности Git

## Снимки, а не различия

Основное отличие Git от любой другой системы контроля версий (включая Subversion и её собратьев) — это **подход к работе со своими данными**. Концептуально, большинство других систем хранят информацию в виде **списка изменений в файлах**. Эти системы (CVS, Subversion, Perforce, Bazaar и т. д.) представляют хранимую информацию в виде набора файлов и изменений, сделанных в каждом файле, по времени (обычно это называют контролем версий, основанным на различиях).

*Хранение данных как набора изменений относительно первоначальной версии каждого из файлов (источник: [git-scm.com/book](https://git-scm.com/book/ru/v2/Введение-Что-такое-Git%3F))*:

![Список изменений в файлах](images/deltas.png)

Git не хранит и не обрабатывает данные таким способом. Вместо этого, подход Git к хранению данных больше похож на **набор снимков** миниатюрной файловой системы. Каждый раз, когда вы делаете коммит, то есть сохраняете состояние своего проекта в Git, система запоминает, как выглядит каждый файл в этот момент, и сохраняет ссылку на этот снимок. Для увеличения эффективности, если файлы не были изменены, Git не запоминает эти файлы вновь, а только создаёт ссылку на предыдущую версию идентичного файла, который уже сохранён. Git представляет свои данные как, скажем, поток снимков.

*Хранение данных как снимков проекта во времени (источник: [git-scm.com/book](https://git-scm.com/book/ru/v2/Введение-Что-такое-Git%3F))*:

![Список изменений в файлах](images/snapshots.png)

Это очень важное отличие между Git и почти любой другой VCS. Git переосмысливает практически все аспекты контроля версий, которые были скопированы из предыдущего поколения большинством других систем. Это делает Git больше похожим на миниатюрную файловую систему с удивительно мощными утилитами, надстроенными над ней, нежели просто на VCS.

## Почти все операции выполняются локально

Для работы большинства операций **в Git достаточно локальных файлов и ресурсов** — в основном, системе не нужна никакая информация с других компьютеров в вашей сети. Вся история проекта хранится прямо на вашем локальном диске, большинство операций кажутся чуть ли не мгновенными.

Для примера, чтобы посмотреть историю проекта, Git не нужно соединяться с сервером для её получения и отображения — система просто считывает данные напрямую из локальной базы данных. Это означает, что вы увидите историю проекта практически моментально. Если вам необходимо посмотреть изменения, сделанные между текущей версией файла и версией, созданной месяц назад, Git может найти файл месячной давности и локально вычислить изменения, вместо того, чтобы запрашивать удалённый сервер выполнить эту операцию, либо вместо получения старой версии файла с сервера и выполнения операции локально.

Это также означает, что есть лишь небольшое количество действий, которые вы не сможете выполнить, если вы находитесь оффлайн или не имеете доступа к VPN в данный момент. Если вы в самолёте или в поезде и хотите немного поработать, вы сможете создавать коммиты без каких-либо проблем (в вашу локальную копию, помните?): когда будет возможность подключиться к сети, все изменения можно будет синхронизировать. Если вы ушли домой и не можете подключиться через VPN, вы всё равно сможете работать. Добиться такого же поведения во многих других системах либо очень сложно, либо вовсе невозможно. В Perforce, для примера, если вы не подключены к серверу, вам не удастся сделать многого; в Subversion и CVS вы можете редактировать файлы, но вы не сможете сохранить изменения в базу данных (потому что вы не подключены к БД). Всё это может показаться не таким уж и значимым, но вы удивитесь, какое большое значение это может иметь.

*Программирование без интернета (источник: [habr.com](https://habr.com/ru/post/319276/))*:

![Программирование без интернета](images/programmer-without-internet.png)

## Целостность Git

В Git для всего вычисляется хеш-сумма, и только потом происходит сохранение. В дальнейшем обращение к сохранённым объектам происходит по этой хеш-сумме. Это значит, что невозможно изменить содержимое файла или каталога так, чтобы Git не узнал об этом. Данная функциональность встроена в Git на низком уровне и является неотъемлемой частью его философии. Вы не потеряете информацию во время её передачи и не получите повреждённый файл без ведома Git.

Механизм, которым пользуется Git при вычислении хеш-сумм, называется SHA-1 хеш. Это строка длиной в 40 шестнадцатеричных символов (0-9 и a-f), она вычисляется на основе содержимого файла или структуры каталога. SHA-1 хеш выглядит примерно так:

```bash
24b9da6552252987aa493b52f8696cd6d3b00373
```

Вы будете постоянно встречать хеши в Git, потому что он использует их повсеместно. На самом деле, Git сохраняет все объекты в свою базу данных не по имени, а по хеш-сумме содержимого объекта.

*Is a Git Repository a Blockchain?*:

![Git SHA example](images/git-sha-example.png)

## Git обычно только добавляет данные

Когда вы производите какие-либо действия в Git, практически все из них только добавляют новые данные в базу Git. Очень сложно заставить систему удалить данные либо сделать что-то, что нельзя впоследствии отменить. Как и в любой другой VCS, вы можете потерять или испортить свои изменения, пока они не зафиксированы, но после того, как вы зафиксируете снимок в Git, будет очень сложно что-либо потерять, особенно, если вы регулярно синхронизируете свою базу с другим репозиторием.

Всё это превращает использование Git в одно удовольствие, потому что мы знаем, что можем экспериментировать, не боясь серьёзных проблем. Для более глубокого понимания того, как Git хранит свои данные и как вы можете восстановить данные, которые кажутся утерянными, см. Операции отмены.

## Три состояния

У Git есть три основных состояния, в которых могут находиться ваши файлы: *изменён* (modified), *индексирован* (staged) и *зафиксирован* (committed):

- К **изменённым** относятся файлы, которые поменялись, но ещё не были зафиксированы.
- **Индексированный** — это изменённый файл в его текущей версии, отмеченный для включения в следующий коммит.
- **Зафиксированный** значит, что файл уже сохранён в вашей локальной базе.

Мы подошли к трём основным секциям проекта Git: *рабочая копия* (working tree), *область индексирования* (staging area) и *каталог Git* (Git directory). Подробнее остановимся на секциях:

- **Рабочая копия** является снимком одной версии проекта. Эти файлы извлекаются из сжатой базы данных в каталоге Git и помещаются на диск, для того чтобы их можно было использовать или редактировать.
- **Область индексирования** — это файл, обычно находящийся в каталоге Git, в нём содержится информация о том, что попадёт в следующий коммит. Её техническое название на языке Git — "индекс", но фраза "область индексирования" также работает.
- **Каталог Git** — это то место, где Git хранит метаданные и базу объектов вашего проекта. Это самая важная часть Git и это та часть, которая копируется при клонировании репозитория с другого компьютера.

*Рабочая копия, область индексирования и каталог Git (источник: [git-scm.com/book](https://git-scm.com/book/ru/v2/Введение-Что-такое-Git%3F))*:

![Рабочая область](images/areas.png)

**Базовый подход в работе с Git** выглядит так:

1. Изменяете файлы вашей *рабочей копии*.
2. Выборочно добавляете в индекс только те изменения, которые должны попасть в следующий коммит, добавляя тем самым снимки только этих изменений в *индекс*.
3. Когда вы делаете коммит, используются файлы из индекса как есть, и этот снимок сохраняется в ваш *каталог Git*.

## Атрибуция

При подготовке статьи использован материал:

- [git-scm.com/book](https://git-scm.com/book/ru/v2/)
- [smartiqa.ru/courses/git](https://smartiqa.ru/courses/git/lesson-2)
